#include <iomicro.h>

void  printHex(const char *s, int n)
{
   int j;
   for (j = 0; j < n; j++) {
      printf("%02X", (unsigned char)s[j]);
   }
   printf("\n");
}

void  printAscii(const char *s, int n)
{
   for (int j = 0; j < n; j++) {
      printf("%c ", s[j]);
   }
   printf("\n");
}

int   initSerialPort(int mode)
{
   int fd = open("/dev/ttyS0", mode);
   if (fd < 0) {
      printf("puerto serial deshabilitado\n");
      return fd;
   }
   tcflush(fd, TCIOFLUSH);
   setOptions(fd);
   return fd;
}

void  closeSerialport(int fd)
{
   tcflush(fd, TCIOFLUSH);
   close(fd);
}

void  setNumberOfChars(int fd, int min)
{
   struct termios options;
   tcgetattr(fd, &options);
   options.c_cc[VMIN] = min;
   tcsetattr(fd, TCSANOW, &options);
}

int   copyString(char *s1, const char *s2, int i, int *XOR)
{
   int n = strlen(s2);
   for (int j = 0; j < n; j++) {
      s1[i++] = s2[j];
      *XOR ^= s2[j];
   }
   return n;
}

int   copyHeader(char *s)
{
   const char *header = "$OnpE";
   strcpy(s, header);
   return strlen(header);
}

int   deviceSitch(int fd, const char *CC)
{
   if (fd <= 0) {return -1;}
   char command[256];
   int i = 0, XOR = 0;
   i += copyHeader(command);
   command[i++] = 3;
   command[i++] = 0;
   i += copyString(command, CC, i, &XOR);
   command[6] = XOR ^ command[5];
   command[i] = 0x0;
   int r = write(fd, command, i);
   char rpta[4];
   r = readMicroSocket(rpta);
   rpta[r] = 0x0;
   if (r == 0) {
      return -1;
   }
   if (rpta[1] == 'K') {
      return r;
   } else {
      return -1;
   }
}

void  setOptions(int fd)
{
   struct termios options;
   tcgetattr(fd, &options);
   cfsetispeed(&options, B115200);
   cfsetospeed(&options, B115200);
   options.c_cflag |= (CLOCAL | CREAD);
   options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
   options.c_oflag &= ~OPOST;
   options.c_iflag &= ~(IXON | IXOFF | IXANY);
   options.c_cflag &= ~CRTSCTS;
   tcsetattr(fd, TCSANOW, &options);
}

int   readMicroSocket(char *str)
{
   int s, l, i;
   struct sockaddr_un remote;
   if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
      perror("socket");
      return -1;
   }
   remote.sun_family = AF_UNIX;
   strcpy(remote.sun_path, USOCKETADDRESS);
   l = strlen(remote.sun_path) + sizeof(remote.sun_family);

   int connected;
   connected = 0;
   for (i = 0; i < 30; i++) {
      if (connect(s, (struct sockaddr *)&remote, l) == -1) {
         usleep(400000);
      } else {
         connected = 1;
         break;
      }
   }

   if (connected == 0) {
      printf("no conectado...!!!");
      close(s);
      return -1;
   }

   if ((i = recv(s, str, 256, 0)) > 0) {
      str[i] = 0x0;
   } else {
      if (i < 0) {
         perror("recv");
      } else {
         printf("conexion con el servidor cerrada\n");
      }
      return -1;
   }

   if (close(s) == -1) {
      perror("close");
      return -1;
   }

   return i;
}

int   openGate(int fd, char c)
{
   if (fd < 0) return -1;
   char command[256];
   int i = 0, XOR = 0;
   i += copyHeader(command);
   command[i++] = 4;
   command[i++] = 0;
   i += copyString(command, "GA", i, &XOR);
   command[i++] = c;
   XOR = XOR ^ c;
   command[6] = XOR ^ command[5];
   command[i] = 0x0;
   int r = write(fd, &command, i);
   char rpta[3];
   r = readMicroSocket(rpta);
   if (r < 1) return 0;
   rpta[r] = 0x0;
   printf("OpenGate end: %s\n", rpta);

   if (rpta[0] == 'G' && rpta[1] == 'K')  return r;
   else                                   return 0;
}

int   runCommand(int fd, const char *CC, char *twobytes)
{
   if (fd <= 0) return -1;

   char command[256];
   int i = 0, XOR = 0;

   i += copyHeader(command);
   command[i++] = 3;
   command[i++] = 0;

   i += copyString(command, CC, i, &XOR);

   command[6] = XOR ^ command[5];
   command[i] = 0x0;

   int r = write(fd, &command, i);

   char rpta[8] = {0x0};
   r = readMicroSocket(rpta);
   if (r == 0) return -1;

   printHex(rpta, 8);
   twobytes[0] = rpta[2];
   twobytes[1] = rpta[3];

   if (rpta[1] == 'K')  return r;
   else                 return -1;
}
